package org.demo.test.socket.server;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

public class AIOSocketServer {

	private static Logger log = Logger.getLogger(AIOSocketServer.class.getClass());
	
	public static void main(String args[]) throws Exception{
		ExecutorService threadPool = Executors.newFixedThreadPool(2);
		AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(threadPool);
		AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open(group);
		serverSocket.bind(new InetSocketAddress(6666));
		log.info("服务启动："+6666);
		serverSocket.accept(null, new ServerSocketChannelHandle(serverSocket));
		log.info("服务端接收连接!");
		
		synchronized (log) {
			log.wait();
		}
	}
}

class ServerSocketChannelHandle implements CompletionHandler<AsynchronousSocketChannel, Void>{

	private static Logger log = Logger.getLogger(ServerSocketChannelHandle.class.getClass());
	
	private AsynchronousServerSocketChannel serverSocket;
	
	public ServerSocketChannelHandle(AsynchronousServerSocketChannel serverSocket){
		this.serverSocket = serverSocket;
	}
	
	@Override
	public void completed(AsynchronousSocketChannel socketChannel, Void attachment) {
		log.info("socket connecting");
		this.serverSocket.accept(attachment, this);
		ByteBuffer bb = ByteBuffer.allocate(50);
		socketChannel.read(bb, new StringBuffer(), new SocketChannelReadHandle(bb, socketChannel));
	}

	@Override
	public void failed(Throwable exc, Void attachment) {
	}
}

class SocketChannelReadHandle implements CompletionHandler<Integer, StringBuffer>{

	private static Logger log = Logger.getLogger(ServerSocketChannelHandle.class.getClass());
	
	private AsynchronousSocketChannel socketChannel;
	
	private ByteBuffer bb;
	
	public SocketChannelReadHandle(ByteBuffer bb, AsynchronousSocketChannel socketChannel){
		this.bb = bb;
		this.socketChannel = socketChannel;
	}
	
	@Override
	public void completed(Integer result, StringBuffer historyContext) {
		if(result == -1){
			try{
				this.socketChannel.close();
			}catch(IOException e){
				e.printStackTrace();
			}
			return;
		}
		log.info("从通道中读取数据!");
		this.bb.flip();
		byte[] contexts = new byte[1024];
		this.bb.get(contexts,0,result);
		this.bb.clear();
		
		try {
			String nowcontext = new String(contexts,0,result,"UTF-8");
			historyContext.append(nowcontext);
			log.info("historyContext:"+historyContext);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(historyContext.indexOf("#") == -1){
			log.info("本次接收还未结束!");
			this.socketChannel.read(this.bb, historyContext, this);
			return;
		}
		log.info("本次接收结束，重新注册监听!");
		try{
			ByteBuffer res = ByteBuffer.wrap("服务器处理结束了!".getBytes());
			socketChannel.write(res);
			this.socketChannel.close();
		}catch(IOException e){
			e.printStackTrace();
		}
	}

	@Override
	public void failed(Throwable exc, StringBuffer attachment) {
		// TODO Auto-generated method stub
		
	}
}
